using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Web;

namespace Omniture.API.Generators
{
	internal class CodeCompiler
	{
		#region Class Members

		private string _baseFolder;
		private string _referenceFolder;
		private string _csharpCompilerPath;
		private string _batchFilePath;
		private Generator _generator = null;
		private string _destinationPath = "";
		private string _sourceFolder = "";

		#endregion

		#region Constructors

		public CodeCompiler(Generator generator, string tempFolder, string destinationPath, string sourceFolder)
		{
			_sourceFolder = sourceFolder;
			_destinationPath = destinationPath;
			_generator = generator;
			_baseFolder = tempFolder;
			FileInfo fi = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
			_referenceFolder = fi.DirectoryName;
			_csharpCompilerPath = @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe";
			_batchFilePath = Path.Combine(_referenceFolder, "Build.bat");
		}

		#endregion

		#region Methods

		public void Compile()
		{
			Directory.CreateDirectory(Path.Combine(_baseFolder, "Reference"));
			//File.Copy(Path.Combine(_referenceFolder, "CeleriQ.API.dll"), Path.Combine(_baseFolder, @"Reference\CeleriQ.API.dll"));

			//Begin the compilation process
			this.Compile(string.Format(_generator.GetCompilationString(), "\"" + _baseFolder + "\""));

			string outputFile = Path.Combine(_baseFolder, @"Reference\" + _generator.ProjectName + ".dll");
			File.Copy(outputFile, Path.Combine(_destinationPath, _generator.ProjectName + ".dll"), true);

			//Copy source code
			if (_sourceFolder != "")
			{
				string folder1 = Path.Combine(_baseFolder, BaseTemplate.GetProjectName(_generator.OmnitureProject));
				this.CopyDirectory(folder1, _sourceFolder, true);				
			}

			//Remove the temp folder
			Directory.Delete(_baseFolder, true);

		}

		public void Compile(string compilationString)
		{
			string cscProcessPath = _csharpCompilerPath;

			ProcessStartInfo cscProcessInfo = new ProcessStartInfo(_csharpCompilerPath);
			cscProcessInfo.CreateNoWindow = true;
			cscProcessInfo.UseShellExecute = false;
			cscProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
			cscProcessInfo.Arguments = compilationString;
			cscProcessInfo.RedirectStandardOutput = true;

			Process cscProcess = new Process();
			cscProcess.StartInfo = cscProcessInfo;
			cscProcess.Start();
			string compilerOutput = cscProcess.StandardOutput.ReadToEnd();
			cscProcess.StandardOutput.Close();

			cscProcess.WaitForExit(30000);

			if (cscProcess.ExitCode != 0)
				throw new ApplicationException("A compilation error occurred. Detailed output: \n" + compilerOutput);
		}

		private void CopyDirectory(string sourcePath, string destPath, bool overwrite)
		{
			System.IO.DirectoryInfo sourceDir = new System.IO.DirectoryInfo(sourcePath);
			System.IO.DirectoryInfo destDir = new System.IO.DirectoryInfo(destPath);
			if (sourceDir.Exists)
			{
				if (!destDir.Exists)
					destDir.Create();

				foreach (System.IO.FileInfo file in sourceDir.GetFiles())
				{
					if (overwrite)
						file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), true);
					else if ((System.IO.File.Exists(System.IO.Path.Combine(destDir.FullName, file.Name))) == false)
						file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), false);
				}

				foreach (System.IO.DirectoryInfo dir in sourceDir.GetDirectories())
				{
					CopyDirectory(dir.FullName, System.IO.Path.Combine(destDir.FullName, dir.Name), overwrite);
				}
			}
		}

		#endregion

	}
}